package com.luoshizhen.lease.common.result;

import lombok.Data;

/**
 * 全局统一返回结果类
 */
@Data
public class Result<T> {

    //返回码
    private Integer code;

    //返回消息
    private String message;

    //返回数据
    private T data;

    public Result() {
    }

    /**
     * 构建一个包含指定数据的结果对象
     * 此方法用于封装数据到Result对象中，提供统一的数据返回格式
     *
     * @param data 泛型参数，表示要封装到Result对象中的数据如果为null，则Result对象中的数据将为空
     * @return 返回一个Result对象，包含输入的数据或空数据
     */
    private static <T> Result<T> build(T data) {
        // 创建一个Result对象，用于封装返回的数据
        Result<T> result = new Result<>();
        // 检查输入数据是否为null，如果不为null，则设置到Result对象中
        if (data != null)
            result.setData(data);
        // 返回封装了数据或空数据的Result对象
        return result;
    }

    /**
     * 构建一个带有特定结果码和消息的Result对象
     * 此方法用于当需要创建一个包含特定业务数据（body）以及特定结果码和消息的Result对象时
     * 通过使用泛型，此方法可以适用于任何类型的业务数据
     *
     * @param body            业务数据，可以是任何类型
     * @param resultCodeEnum  结果码枚举，包含结果码和对应的消息
     * @return                返回一个包含业务数据、结果码和消息的Result对象
     */
    public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) {
        // 首先调用build方法创建一个包含业务数据的Result对象
        Result<T> result = build(body);

        // 设置Result对象的结果码和消息，来源于传入的结果码枚举
        result.setCode(resultCodeEnum.getCode());
        result.setMessage(resultCodeEnum.getMessage());

        // 返回构建好的Result对象
        return result;
    }


    /**
     * 创建一个表示成功结果的对象
     * 该方法用于封装一个数据对象，返回一个表示操作成功的Result对象
     * 主要用于简化结果对象的创建过程，使调用者能够专注于处理业务逻辑，而不必关心结果对象的构建细节
     *
     * @param data 要封装到Result对象中的数据，可以是任意类型
     * @param <T>  泛型参数，表示data参数的类型
     * @return 返回一个表示操作成功的Result对象，包含传入的数据和成功的结果码
     */
    public static <T> Result<T> ok(T data) {
        return build(data, ResultCodeEnum.SUCCESS);
    }

    /**
     * 创建一个表示成功结果的对象，但不包含任何数据.
     *
     * @param <T> 泛型参数，表示结果对象中数据的类型.
     * @return 返回一个泛型Result对象，表示操作成功，但没有包含任何数据.
     */
    public static <T> Result<T> ok() {
        return Result.ok(null);
    }

    /**
     * 创建一个表示失败结果的对象
     *
     * @param <T> 泛型参数，表示结果对象中数据的类型
     * @return 返回一个泛型类型为T的Result对象，表示失败的结果
     */
    public static <T> Result<T> fail() {
        return build(null, ResultCodeEnum.FAIL);
    }

    /**
     * 创建一个表示失败结果的对象
     * 此方法用于快速构建一个带有指定状态码和消息的失败结果
     *
     * @param <T> 结果对象中数据的类型
     * @param code 结果的状态码，用于表示具体的错误类型
     * @param message 结果的消息，用于提供错误的详细信息
     * @return 返回一个表示失败结果的对象，包含状态码和消息
     */
    public static <T> Result<T> fail(Integer code, String message) {
        // 初始化结果对象，此时数据为null，表示没有成功获取到数据
        Result<T> result = build(null);
        // 设置结果对象的状态码为传入的code
        result.setCode(code);
        // 设置结果对象的消息为传入的message
        result.setMessage(message);
        // 返回构建好的结果对象
        return result;
    }
}
